home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr49 / 109_01.zip / UCSD2CPM.C < prev    next >
Text File  |  1993-06-26  |  12KB  |  504 lines

  1. /*    -------------------------------------------------------
  2.     *** Template for Procedure Heading ***
  3.  
  4.     Name:
  5.     Result:
  6.     Errors:
  7.     Globals:
  8.     Macros:
  9.     Procedures:
  10.  
  11.     Action:
  12.  
  13.     ------------------------------------------------------- */
  14.  
  15. /*    : : : : : : : : : : : : : : : : : : : : : : : : : : : :
  16.  
  17.     ucsd2cpm -- Transfer '.TEXT' files from a UCSD directory
  18.             formatted disk to a CP/M directory formatted
  19.             disk.
  20.  
  21.         1) header blocks removed
  22.         2) linefeeds added after carriage returns
  23.         3) indents converted to appropriate # of spaces
  24.         4) filler nulls removed
  25.         5) control-A's removed    (added 2/13/80 hrm)
  26.  
  27.     : : : : : : : : : : : : : : : : : : : : : : : : : : : : */
  28.  
  29.  
  30.  
  31.  
  32.  
  33. /*    : : : : : : : : : : : : : : : : : : : : : : : : : : : :
  34.  
  35.         Constants
  36.  
  37.     : : : : : : : : : : : : : : : : : : : : : : : : : : : : */
  38.  
  39.  
  40. #define    DLE    0x10        /* Data Link Escape -- indent flag */
  41. #define CR    0x0D        /* carriage return */
  42. #define LF    0x0A        /* linefeed */
  43. #define NULL    0        /* ascii null */
  44. #define CPM_EOF    0X1A        /* CP/M ascii endfile mark */
  45.  
  46. #define    TRUE    1        /* booleans */
  47. #define    FALSE    0
  48.  
  49. #define    SEL_DSK    14        /* bdos function number */
  50. #define    SET_DMA    26        /* bdos function number */
  51.  
  52. #define    SET_TRK    9        /* bios index number */
  53. #define    SET_SEC    10        /* bios index number */
  54. #define    READ    12        /* bios index number */
  55.  
  56. #define    DUMMY    0        /* dummy parameter for bios routine */
  57.  
  58. #define    EOF_F    0xFFFF        /* end of file flag */
  59. #define    D_ENT_SZ 26        /* UCSD directory entry size */
  60. #define    D_TITLE    6        /* offset to entry title */
  61. #define    UCSD_NAM_SZ 20        /* size of the name part of ucsd dir entry */
  62. #define UCSD_DIR_SZ 2048    /* size of UCSD directory in bytes */
  63.  
  64. #define    SECT_SIZE 128        /* bytes per physical sector */
  65. #define BLOK_SIZE 512        /* bytes per UCSD logical block */
  66. #define    SECT_PER_BLOK 4        /* physical sectors per logical block */
  67.  
  68.  
  69.  
  70.  
  71. /*    : : : : : : : : : : : : : : : : : : : : : : : : : : : :
  72.  
  73.     Globals    -- these would be static if it were available
  74.  
  75.     : : : : : : : : : : : : : : : : : : : : : : : : : : : : */
  76.  
  77. int lsn;        /* logical sector number */
  78. int lstlsn;        /* last logical sector number */
  79. int nbytes;        /* number of bytes remaining in ucsd file buffer */
  80. char ucsdbuf[BLOK_SIZE]; /* 1 block buffer for ucsd file */
  81. char *ptr;        /* pointer to current byte in ucsd file buffer */
  82.  
  83.  
  84.  
  85.  
  86. /*    : : : : : : : : : : : : : : : : : : : : : : : : : : : :
  87.  
  88.         Global structure type
  89.  
  90.     : : : : : : : : : : : : : : : : : : : : : : : : : : : : */
  91.  
  92.     struct buf {
  93.       int fd;
  94.       int nleft;
  95.       char *nextp;
  96.       char buff[SECT_SIZE];
  97.       };
  98.  
  99. /*    -------------------------------------------------------
  100.  
  101.     Name:        main(argc,argv)
  102.     Result:        ---
  103.     Errors:        invocation syntax
  104.     Globals:    lsn,lstlsn,nbytes,ptr,ucsdbuf
  105.     Macros:        CPM_FILE,UCSD_FILE,UCSD_NAM_SZ
  106.  
  107.     Procedures:    puts(),exit(),force_upr(),printf()
  108.             putchar(),close(),unlink(),strcpy()
  109.             strcat(),getchar(),open(),copy()
  110.             tolower()
  111.  
  112.     Action:        Call copy() to copy a '.TEXT' file
  113.             from a UCSD formatted disk in drive B
  114.             to a user specified file name in
  115.             drive A
  116.  
  117.             Handle invocation errors
  118.             Handle case of already existing
  119.             destination  file
  120.  
  121.     ------------------------------------------------------- */
  122.  
  123. #define CPM_FILE argv[1]
  124. #define UCSD_FILE argv[2]
  125.  
  126. main(argc,argv)
  127.     int argc;
  128.     char *argv[];
  129.     {
  130.     int file_id;
  131.     char ucsdname[UCSD_NAM_SZ];
  132.  
  133.     lsn = lstlsn = nbytes = 0;    /* init globals */
  134.     ptr = ucsdbuf;
  135.  
  136.     if( argc != 3 )    {
  137.       puts("Proper invocation form is:\n\n");
  138.       puts("UCSD2CPM <cpm-file-name> <ucsd-file-name>\n");
  139.       puts("This copies B:<ucsd-file-name>.TEXT to A:<cpm-file-name>\n");
  140.       exit(1);
  141.       }
  142.     force_upr(UCSD_FILE);    /* make <ucsd-file-name> upper case */
  143.     if( (file_id = open(CPM_FILE,0)) >= 0 ) {
  144.       printf("%s already exists. Delete it ? ",CPM_FILE);
  145.       if( tolower(getchar()) != 'y' ) {
  146.         puts("\naborted\n");
  147.         exit(1);
  148.         }
  149.       putchar('\n');
  150.       close(file_id);
  151.       unlink(CPM_FILE);
  152.       }
  153.     else
  154.       close(file_id);
  155.     strcpy(ucsdname,UCSD_FILE);
  156.     strcat(ucsdname,".TEXT");
  157.     if(copy(ucsdname,CPM_FILE))
  158.       printf("\n\nno such file %s .. aborted\n",ucsdname);
  159.     exit(0);
  160.     }
  161.  
  162. /*    -------------------------------------------------------
  163.  
  164.     Name:        copy (ucsd_file,cpm_file)
  165.     Result:        TRUE if error , FALSE if transfer ok
  166.  
  167.     Errors:        no such '.TEXT' file
  168.  
  169.     Globals:    struct buf,
  170.     Macros:        TRUE,EOF_F,CR,DLE,NULL,CPM_EOF,FALSE
  171.  
  172.     Procedures:    find_file(),fcreat(),getbyte()
  173.             putc(),fflush(),fclose()
  174.  
  175.     Action:        Find '.TEXT' file in UCSD directory
  176.             on drive B
  177.             Create user specified file on
  178.             drive A
  179.             copy file content from UCSD to CP/M
  180.             car by char translating:
  181.                 Skip header block
  182.                 Ignore NULL's
  183.                 Add LF after CR
  184.                 Convert DLE <count> to
  185.                 appropriate number of spaces
  186.             close output file
  187.  
  188.     ------------------------------------------------------- */
  189.  
  190. copy(ucsd_file,cpm_file)
  191.     char *ucsd_file,*cpm_file;
  192.     {
  193.     struct buf tofile;
  194.     int c;
  195.  
  196.     if( ! find_file(ucsd_file) )        /* no such file */
  197.       return TRUE;
  198.     fcreat(cpm_file,&tofile);
  199.     while( (c = getbyte()) != EOF_F )
  200.       switch(c) {
  201.  
  202.         case CR:    putc(CR,&tofile);    /* LF after CR */
  203.             putc(LF,&tofile);
  204.             break;
  205.  
  206.         case DLE:    for( c = (getbyte() - 32); c; c-- )
  207.               putc(' ',&tofile);    /* fill spaces */
  208.             break;
  209.  
  210.         case '\1':                /* ignore ^A's */
  211.         case NULL:    break;            /* ignore nulls */
  212.  
  213.         default:    putc(c,&tofile);    /* pass char unmodified */
  214.             break;
  215.         }
  216.     putc(CPM_EOF,&tofile);            /* send cp/m ascii endfile */
  217.     fflush(&tofile);
  218.     fclose(&tofile);
  219.     return FALSE;                /* signal transfer ok */
  220.     }
  221.  
  222. /*    -------------------------------------------------------
  223.  
  224.     Name:        getbyte()
  225.     Result:        next sequential byte from UCSD '.TEXT' file
  226.     Errors:
  227.     Globals:    lsn,lstlsn,nbytes,ptr,ucsdbuf[]
  228.     Macros:        EOF_F,BLOK_SIZE,SECT_PER_BLOK
  229.     Procedures:    read_ucsd()
  230.  
  231.     Action:        read block at a time
  232.             pass along byte at a time
  233.             return EOF_F if end of UCSD file
  234.  
  235.     ------------------------------------------------------- */
  236.  
  237.  
  238. getbyte()
  239.     {
  240.     if( lsn > lstlsn)
  241.       return EOF_F;
  242.     if( nbytes-- )
  243.       return *ptr++;
  244.     read_ucsd(ucsdbuf,lsn,1);
  245.     nbytes = (BLOK_SIZE-1);
  246.     ptr = ucsdbuf;
  247.     lsn += SECT_PER_BLOK;
  248.     return *ptr++;
  249.     }
  250.  
  251.  
  252. /*    -------------------------------------------------------
  253.  
  254.     Name:        fclose(file)
  255.     Result:        status of closing action
  256.     Errors:        ---
  257.     Globals:    struct buf
  258.     Macros:        ---
  259.     Procedures:    close()
  260.  
  261.     Action:        file open for buffered input
  262.             or output is closed
  263.  
  264.     ------------------------------------------------------- */
  265.  
  266.  
  267. fclose(file)
  268.     struct buf *file;
  269.     {
  270.     return close( file->fd );
  271.     }
  272.  
  273. /*    -------------------------------------------------------
  274.  
  275.     Name:        find_file(ucsd_name)
  276.     Result:        TRUE if found, FALSE if not found
  277.     Errors:
  278.     Globals:    lsn,lstlsn
  279.     Macros:        D_ENT_SZ,SECT_PER_BLOK,D_TITLE
  280.             TRUE,FALSE,UCSD_DIR_SZ
  281.  
  282.     Procedures:    read_ucsd()
  283.  
  284.     Action:        ---
  285.  
  286.     ------------------------------------------------------- */
  287.  
  288.  
  289. find_file(ucsd_name)
  290.     char *ucsd_name;
  291.     {
  292.     char ucsd_dir[UCSD_DIR_SZ];
  293.     char *dir,*saved_dir,*name;
  294.     int name_len;
  295.  
  296.     name = ucsd_name;
  297.     read_ucsd(ucsd_dir,(2*SECT_PER_BLOK),4);
  298.     dir = &ucsd_dir[D_TITLE + D_ENT_SZ];    /* skip title block */
  299.     while ( dir < &ucsd_dir[UCSD_DIR_SZ] ) {
  300.       saved_dir = dir;
  301.       if( (name_len = *dir++) <=0 || name_len > 19 )
  302.         return FALSE;
  303.       while( *dir++ == *name++ ) {
  304.         if( --name_len )    /* continue comparison check */
  305.           ;
  306.         else {                /* entry found */
  307.           dir = saved_dir - D_TITLE;    /* point to alloc. info. */
  308.           lsn = *dir++;
  309.           lsn += *dir++ << 8;   /* lsn = starting logical block number */
  310.           lsn += 2;            /* bypass header blocks */
  311.           lsn *= SECT_PER_BLOK; /* 1'st logical sector number */
  312.  
  313.           lstlsn = *dir++;
  314.           lstlsn += *dir++ << 8;    /* lstlsn = ending logical block # */
  315.           lstlsn *= SECT_PER_BLOK;    /* lstlsn = last logical sector # */
  316.           return TRUE;        /* indicate file found */
  317.           }
  318.         }
  319.       name = ucsd_name;        /* reset comparison name pointer */
  320.       dir = saved_dir + D_ENT_SZ;    /* point at next entry name */
  321.       }
  322.     return FALSE;                /* no such file */
  323.     }
  324.  
  325. /*    -------------------------------------------------------
  326.  
  327.     Name:        read_ucsd()
  328.     Result:        status of selecting drive A
  329.     Errors:        sector read error
  330.     Globals:    ---
  331.     Macros:        SEL_DSK,SET_DMA,SET_TRK,SET_SEC
  332.             READ,DUMMY,SECT_SIZE
  333.     Procedures:    bios(),bdos(),printf(),exit()
  334.  
  335.     Action:        Read count blocks from drive B
  336.             into buf starting at UCSD logical
  337.             record number rn
  338.  
  339.     ------------------------------------------------------- */
  340.  
  341.  
  342. read_ucsd(buf,rn,count)
  343.     char *buf;
  344.     unsigned rn;
  345.     int count;
  346.     {
  347.     char bios();
  348.     int seccnt; seccnt = count*4;
  349.  
  350.     bdos(SEL_DSK,1);
  351.     while( seccnt-- ) {
  352.       bdos(SET_DMA,buf);
  353.       bios(SET_TRK,track(rn));
  354.       bios(SET_SEC,sector(rn));
  355.       if( bios(READ,DUMMY) ) {
  356.         printf("read error @ track %2d sector %2d",track(rn),sector(rn));
  357.         exit(1);
  358.         }
  359.       buf += SECT_SIZE;
  360.       rn++;
  361.       }
  362.     return bdos(SEL_DSK,0);
  363.     }
  364.  
  365. /*    -------------------------------------------------------
  366.  
  367.     Name:        sector(rn)
  368.     Result:        absolute sector number
  369.     Errors:        ---
  370.     Globals:    ---
  371.     Macros:        ---
  372.     Procedures:    ---
  373.  
  374.     Action:        convert logical record number
  375.             to absolute sector
  376.  
  377.             maps logical records to physical sectors
  378.             by selecting every second sector in order
  379.             (accounting for the modulo 26 process)
  380.             on the diskette except that at a track
  381.             switchover point there is an additional
  382.             'gap' of 6 sectors (total of 7) to allow
  383.             for the drive to seek. This is UCSD's
  384.             attempt to minimize disk access    time.
  385.  
  386.     ------------------------------------------------------- */
  387.  
  388. sector(rn)
  389.     unsigned rn;
  390.     {
  391.     unsigned t1,t2,trk,t3,sect;
  392.  
  393.     t1 = rn % 26;
  394.     t2 = t1 << 1;
  395.     if(t1 > 12)
  396.       t2++;
  397.     trk = rn/26;        /* zero based absolute track */
  398.     t3 = t2 + 6*trk;    /* new logical sector number */
  399.     sect = t3 % 26;        /* new zero based absolute sector */
  400.     return ++sect;        /* one based absolute sector */
  401.     }
  402.  
  403. /*    -------------------------------------------------------
  404.  
  405.     Name:        track(rn)
  406.     Result:        absolute track number
  407.     Errors:        ---
  408.     Globals:    ---
  409.     Macros:        ---
  410.     Procedures:    ---
  411.  
  412.     Action:        convert logical sector number to
  413.             absolute track This is simply the modulo
  414.             26 process except that track 0 is not
  415.             considered part of the logical
  416.             sector space.
  417.  
  418.     ------------------------------------------------------- */
  419.  
  420.  
  421. track(rn)
  422.     unsigned rn;
  423.     {
  424.     return rn/26 + 1;
  425.     }
  426.  
  427. /*    -------------------------------------------------------
  428.  
  429.     Name:        index(str,sstr)
  430.     Result:        position of string sstr in string str
  431.             -1 if not a substring
  432.     Errors:        ---
  433.     Globals:    ---
  434.     Macros:        ---
  435.     Procedures:    ---
  436.  
  437.     Action:        ---
  438.  
  439.     ------------------------------------------------------- */
  440.  
  441.  
  442. index(str,sstr)
  443.     char *str,*sstr;
  444.     {
  445.     int first_match;
  446.  
  447.     if( *sstr == 0 )  /* null string is a substring of all strings */
  448.       return 0;
  449.     for( first_match=0; *str != *sstr; first_match++)
  450.       if( *str == 0 )
  451.         return -1;
  452.       else
  453.         str++;
  454.     while( *sstr )
  455.       if( *str++ != *sstr++ )
  456.         return -1;
  457.     return first_match;
  458.     }
  459.  
  460. /*    -------------------------------------------------------
  461.  
  462.     Name:        force_upr(string)
  463.     Result:        ---
  464.     Errors:        ---
  465.     Globals:    ---
  466.     Macros:        ---
  467.     Procedures:    ---
  468.  
  469.     Action:        force each char of string to upper case
  470.  
  471.     ------------------------------------------------------- */
  472.  
  473. force_upr(string)
  474.     char *string;
  475.     {
  476.     while(*string)
  477.       *string = *string++;
  478.     return;
  479.     }
  480.  
  481. /*    -------------------------------------------------------
  482.  
  483.     Name:        print(string,n)
  484.     Result:        ---
  485.     Errors:        ---
  486.     Globals:    ---
  487.     Macros:        ---
  488.     Procedures:    putchar()
  489.  
  490.     Action:        print n chars to console starting
  491.             at char pointer string
  492.  
  493.     ------------------------------------------------------- */
  494.  
  495. print(string,n)
  496.     char *string;
  497.     int n;
  498.     {
  499.     while(n--)
  500.       putchar(*string++);
  501.     return;
  502.     }
  503.  
  504.